#include "SteelClientAPI.h"
#include "MainWindow.h"
#include "StyleManager.h"
#include "main/MainPageWidget.h"
#include "main/MainOperationWidget.h"
#include "main/SmeltingConfigWidget.h"
#include "common/VideoWidget.h"

#include <QApplication>
#include <QStyleFactory>
#include <QPalette>
#include <QFont>
#include <QColor>
#include <QMutex>
#include <QMutexLocker>
#include <QDebug>
#include <QString>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <QMetaObject>
#include <QThread>

#include <map>
#include <vector>
#include <exception>
#include <cstring>

namespace {

MainWindow* g_mainWindow = nullptr;
SteelClientWindowHandle fetchVideoWindowHandle();
void notifyVideoWindowHandleForAllNavs();
void requestVideoWindowHandleNotification();

bool isValidNavTreeIndex(NavTreeIndex index)
{
    int value = static_cast<int>(index);
    if (value < 10 || value > 62) {
        return false;
    }
    int group = value / 10;
    int offset = value % 10;
    if (group < 1 || group > 6) {
        return false;
    }
    return offset == 0 || offset == 1 || offset == 2;
}

struct WorkingConditionCallbackInfo {
    int id;
    WorkingConditionCallback callback;
    void* userData;
};

struct OxygenLanceCallbackInfo {
    int id;
    OxygenLanceCallback callback;
    void* userData;
};

struct MaterialCallbackInfo {
    int id;
    MaterialCallback callback;
    void* userData;
};

struct LoginCallbackInfo {
    int id;
    LoginCallback callback;
    void* userData;
};

struct MainPageWorkingConditionCallbackInfo {
    int id;
    MainPageWorkingConditionCallback callback;
    void* userData;
};

struct MainPageMaterialCallbackInfo {
    int id;
    MainPageMaterialCallback callback;
    void* userData;
};

struct MainPageOxygenLanceCallbackInfo {
    int id;
    MainPageOxygenLanceCallback callback;
    void* userData;
};

struct MainPageBlowingCallbackInfo {
    int id;
    MainPageBlowingCallback callback;
    void* userData;
};

struct MainPageChartCallbackInfo {
    int id;
    MainPageChartCallback callback;
    void* userData;
};

struct MainPageOperStageCallbackInfo {
    int id;
    MainPageOperStageCallback callback;
    void* userData;
};

struct MainPageOperTotalCallbackInfo {
    int id;
    MainPageOperTotalCallback callback;
    void* userData;
};

struct MainPageProcessCallbackInfo {
    int id;
    MainPageProcessCallback callback;
    void* userData;
};

struct MainPageVideoCallbackInfo {
    int id;
    MainPageVideoCallback callback;
    void* userData;
};

struct MainPageVideoWindowHandleCallbackInfo {
    int id;
    MainPageVideoWindowHandleCallback callback;
    void* userData;
};

struct ApplicationShutdownCallbackInfo {
    int id;
    ApplicationShutdownCallback callback;
    void* userData;
};

struct DebugButtonCallbackInfo {
    int id;
    DebugButtonCallback callback;
    void* userData;
};

class APIDataManager
{
public:
    static APIDataManager& instance()
    {
        static APIDataManager inst;
        return inst;
    }

    void setWorkingConditionData(NavTreeIndex index, const ConfigWorkingConditionData& data)
    {
        ConfigWorkingConditionData dataCopy = data;
        std::vector<WorkingConditionCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            m_workingConditionData[index] = dataCopy;
            callbacks.reserve(m_workingCallbacks.size());
            for (const auto& entry : m_workingCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setOxygenLanceData(NavTreeIndex index, const ConfigOxygenLanceData& data)
    {
        ConfigOxygenLanceData dataCopy = data;
        std::vector<OxygenLanceCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            m_oxygenLanceData[index] = dataCopy;
            callbacks.reserve(m_oxygenCallbacks.size());
            for (const auto& entry : m_oxygenCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMaterialData(NavTreeIndex index, const ConfigMaterialData& data)
    {
        ConfigMaterialData dataCopy = data;
        std::vector<MaterialCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            m_materialData[index] = dataCopy;
            callbacks.reserve(m_materialCallbacks.size());
            for (const auto& entry : m_materialCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageWorkingConditionData(NavTreeIndex index, const MainPageWorkingConditionData& data)
    {
        MainPageWorkingConditionData dataCopy = data;
        dataCopy.count = std::min(dataCopy.count, MAIN_PAGE_WORKING_MAX_ITEMS);
        std::vector<MainPageWorkingConditionCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            m_mainPageWorkingConditionData[index] = dataCopy;
            callbacks.reserve(m_mainPageWorkingCallbacks.size());
            for (const auto& entry : m_mainPageWorkingCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageMaterialData(NavTreeIndex index, const MainPageMaterialData& data)
    {
        MainPageMaterialData dataCopy = data;
        dataCopy.count = std::min(dataCopy.count, MAIN_PAGE_MATERIAL_MAX_ITEMS);
        std::vector<MainPageMaterialCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            m_mainPageMaterialData[index] = dataCopy;
            callbacks.reserve(m_mainPageMaterialCallbacks.size());
            for (const auto& entry : m_mainPageMaterialCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageWorkingConditionItem(NavTreeIndex index, int itemIndex, const char* name, const char* value)
    {
        if (itemIndex < 0 || itemIndex >= MAIN_PAGE_WORKING_MAX_ITEMS) {
            qWarning() << "setMainPageWorkingConditionItem invalid itemIndex:" << itemIndex;
            return;
        }

        MainPageWorkingConditionData dataCopy{};
        std::vector<MainPageWorkingConditionCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            MainPageWorkingConditionData& stored = m_mainPageWorkingConditionData[index];
            
            // 确保索引有效
            if (itemIndex >= stored.count) {
                stored.count = itemIndex + 1;
            }
            
            // 更新项
            MainPageKVItem& item = stored.items[itemIndex];
            if (name) {
                std::strncpy(item.name, name, sizeof(item.name) - 1);
                item.name[sizeof(item.name) - 1] = '\0';
            } else {
                item.name[0] = '\0';
            }
            if (value) {
                std::strncpy(item.value, value, sizeof(item.value) - 1);
                item.value[sizeof(item.value) - 1] = '\0';
            } else {
                item.value[0] = '\0';
            }
            
            dataCopy = stored;
            callbacks.reserve(m_mainPageWorkingCallbacks.size());
            for (const auto& entry : m_mainPageWorkingCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageMaterialItem(NavTreeIndex index, int itemIndex, const char* name, const char* value)
    {
        if (itemIndex < 0 || itemIndex >= MAIN_PAGE_MATERIAL_MAX_ITEMS) {
            qWarning() << "setMainPageMaterialItem invalid itemIndex:" << itemIndex;
            return;
        }

        MainPageMaterialData dataCopy{};
        std::vector<MainPageMaterialCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            MainPageMaterialData& stored = m_mainPageMaterialData[index];
            
            // 确保索引有效
            if (itemIndex >= stored.count) {
                stored.count = itemIndex + 1;
            }
            
            // 更新项
            MainPageKVItem& item = stored.items[itemIndex];
            if (name) {
                std::strncpy(item.name, name, sizeof(item.name) - 1);
                item.name[sizeof(item.name) - 1] = '\0';
            } else {
                item.name[0] = '\0';
            }
            if (value) {
                std::strncpy(item.value, value, sizeof(item.value) - 1);
                item.value[sizeof(item.value) - 1] = '\0';
            } else {
                item.value[0] = '\0';
            }
            
            dataCopy = stored;
            callbacks.reserve(m_mainPageMaterialCallbacks.size());
            for (const auto& entry : m_mainPageMaterialCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageOxygenLanceData(NavTreeIndex index, const MainPageOxygenLanceData& data)
    {
        MainPageOxygenLanceData dataCopy = data;
        std::vector<MainPageOxygenLanceCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            m_mainPageOxygenLanceData[index] = dataCopy;
            callbacks.reserve(m_mainPageOxygenCallbacks.size());
            for (const auto& entry : m_mainPageOxygenCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageBlowingData(NavTreeIndex index, const MainPageBlowingData& data)
    {
        MainPageBlowingData dataCopy = data;
        std::vector<MainPageBlowingCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            m_mainPageBlowingData[index] = dataCopy;
            callbacks.reserve(m_mainPageBlowingCallbacks.size());
            for (const auto& entry : m_mainPageBlowingCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageOxygenLanceField(NavTreeIndex index, const char* fieldName, double value)
    {
        if (!fieldName) {
            qWarning() << "setMainPageOxygenLanceField: fieldName is null";
            return;
        }

        MainPageOxygenLanceData dataCopy{};
        std::vector<MainPageOxygenLanceCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            MainPageOxygenLanceData& stored = m_mainPageOxygenLanceData[index];
            
            // 根据字段名更新对应的字段
            QString field = QString::fromUtf8(fieldName);
            if (field == "氧气流量" || field == "oxygenFlow") {
                stored.oxygenFlow = value;
            } else if (field == "氧枪高度" || field == "lanceHeight") {
                stored.lanceHeight = value;
            } else if (field == "读数吹氧量" || field == "readingBlowQuantity") {
                stored.readingBlowQuantity = value;
            } else if (field == "累计吹氧量" || field == "accumulatedBlowQuantity") {
                stored.accumulatedBlowQuantity = value;
            } else if (field == "转炉角度" || field == "converterAngle") {
                stored.converterAngle = value;
            } else if (field == "氧气压力" || field == "oxygenPressure") {
                stored.oxygenPressure = value;
            } else {
                qWarning() << "setMainPageOxygenLanceField: unknown field name:" << fieldName;
                return;
            }
            
            dataCopy = stored;
            callbacks.reserve(m_mainPageOxygenCallbacks.size());
            for (const auto& entry : m_mainPageOxygenCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageBlowingField(NavTreeIndex index, const char* fieldName, const char* value)
    {
        if (!fieldName) {
            qWarning() << "setMainPageBlowingField: fieldName is null";
            return;
        }

        MainPageBlowingData dataCopy{};
        std::vector<MainPageBlowingCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            MainPageBlowingData& stored = m_mainPageBlowingData[index];
            
            // 根据字段名更新对应的字段
            QString field = QString::fromUtf8(fieldName);
            char* dest = nullptr;
            size_t destSize = 0;
            
            if (field == "当前吹炼时间" || field == "currentBlowingTime") {
                dest = stored.currentBlowingTime;
                destSize = sizeof(stored.currentBlowingTime);
            } else if (field == "预计剩余时间" || field == "estimatedRemainingTime") {
                dest = stored.estimatedRemainingTime;
                destSize = sizeof(stored.estimatedRemainingTime);
            } else if (field == "当前温度" || field == "currentTemperature") {
                dest = stored.currentTemperature;
                destSize = sizeof(stored.currentTemperature);
            } else if (field == "当前碳含量" || field == "currentCarbonContent") {
                dest = stored.currentCarbonContent;
                destSize = sizeof(stored.currentCarbonContent);
            } else if (field == "操作模式" || field == "operatingMode") {
                dest = stored.operatingMode;
                destSize = sizeof(stored.operatingMode);
            } else {
                qWarning() << "setMainPageBlowingField: unknown field name:" << fieldName;
                return;
            }
            
            if (dest && destSize > 0) {
                if (value) {
                    std::strncpy(dest, value, destSize - 1);
                    dest[destSize - 1] = '\0';
                } else {
                    dest[0] = '\0';
                }
            }
            
            dataCopy = stored;
            callbacks.reserve(m_mainPageBlowingCallbacks.size());
            for (const auto& entry : m_mainPageBlowingCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageChartData(NavTreeIndex index, const MainPageChartData& data)
    {
        MainPageChartData dataCopy = data;

        auto clampSeries = [](MainPageChartSeriesData& series) {
            if (series.count < 0) {
                series.count = 0;
            } else if (series.count > MAIN_PAGE_CHART_MAX_POINTS) {
                series.count = MAIN_PAGE_CHART_MAX_POINTS;
            }
        };

        clampSeries(dataCopy.actualLanceSeries);
        clampSeries(dataCopy.standardLanceSeries);
        clampSeries(dataCopy.oxygenFlowSeries);
        clampSeries(dataCopy.limeClassSeries);
        clampSeries(dataCopy.rawWhiteClassSeries);
        clampSeries(dataCopy.ironOreClassSeries);

        std::vector<MainPageChartCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            m_mainPageChartData[index] = dataCopy;
            callbacks.reserve(m_mainPageChartCallbacks.size());
            for (const auto& entry : m_mainPageChartCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageChartTableData(NavTreeIndex index, const MainPageChartTableData& tableData)
    {
        MainPageChartData dataCopy{};
        std::vector<MainPageChartCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            MainPageChartData& stored = m_mainPageChartData[index];
            stored.tableData = tableData;
            dataCopy = stored;
            callbacks.reserve(m_mainPageChartCallbacks.size());
            for (const auto& entry : m_mainPageChartCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageChartTableItem(NavTreeIndex index, int row, int column, const char* value)
    {
        if (row < 0 || row >= MAIN_PAGE_CHART_TABLE_ROWS || column < 0 || column >= MAIN_PAGE_CHART_TABLE_COLUMNS) {
            qWarning() << "setMainPageChartTableItem invalid row/column:" << row << column;
            return;
        }

        MainPageChartData dataCopy{};
        std::vector<MainPageChartCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            MainPageChartData& stored = m_mainPageChartData[index];
            char* dest = stored.tableData.items[row][column];
            if (value) {
                std::strncpy(dest, value, sizeof(stored.tableData.items[row][column]) - 1);
                dest[sizeof(stored.tableData.items[row][column]) - 1] = '\0';
            } else {
                dest[0] = '\0';
            }
            dataCopy = stored;
            callbacks.reserve(m_mainPageChartCallbacks.size());
            for (const auto& entry : m_mainPageChartCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageOperStageData(NavTreeIndex index, const MainPageOperStageData& data)
    {
        MainPageOperStageData dataCopy = data;
        std::vector<MainPageOperStageCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            m_mainPageOperStageData[index] = dataCopy;
            callbacks.reserve(m_mainPageOperStageCallbacks.size());
            for (const auto& entry : m_mainPageOperStageCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageOperStageItem(NavTreeIndex index, int row, int column, const char* value)
    {
        if (row < 0 || row >= MAIN_PAGE_OPER_STAGE_ROWS || column < 0 || column >= MAIN_PAGE_OPER_STAGE_COLUMNS) {
            qWarning() << "setMainPageOperStageItem invalid row/column:" << row << column;
            return;
        }

        MainPageOperStageData dataCopy{};
        std::vector<MainPageOperStageCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            MainPageOperStageData& stored = m_mainPageOperStageData[index];
            char* dest = stored.stageItems[row][column];
            if (value) {
                std::strncpy(dest, value, sizeof(stored.stageItems[row][column]) - 1);
                dest[sizeof(stored.stageItems[row][column]) - 1] = '\0';
            } else {
                dest[0] = '\0';
            }

            dataCopy = stored;
            callbacks.reserve(m_mainPageOperStageCallbacks.size());
            for (const auto& entry : m_mainPageOperStageCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageOperTotalData(NavTreeIndex index, const MainPageOperTotalData& data)
    {
        MainPageOperTotalData dataCopy = data;
        std::vector<MainPageOperTotalCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            m_mainPageOperTotalData[index] = dataCopy;
            callbacks.reserve(m_mainPageOperTotalCallbacks.size());
            for (const auto& entry : m_mainPageOperTotalCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageOperTotalItem(NavTreeIndex index, int row, int column, const char* value)
    {
        if (row < 0 || row >= MAIN_PAGE_OPER_TOTAL_ROWS || column < 0 || column >= MAIN_PAGE_OPER_TOTAL_COLUMNS) {
            qWarning() << "setMainPageOperTotalItem invalid row/column:" << row << column;
            return;
        }
        if (column == 0) {
            qWarning() << "setMainPageOperTotalItem cannot modify header column";
            return;
        }

        MainPageOperTotalData dataCopy{};
        std::vector<MainPageOperTotalCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            MainPageOperTotalData& stored = m_mainPageOperTotalData[index];
            char* dest = stored.totalItems[row][column];
            if (value) {
                std::strncpy(dest, value, sizeof(stored.totalItems[row][column]) - 1);
                dest[sizeof(stored.totalItems[row][column]) - 1] = '\0';
            } else {
                dest[0] = '\0';
            }

            dataCopy = stored;
            callbacks.reserve(m_mainPageOperTotalCallbacks.size());
            for (const auto& entry : m_mainPageOperTotalCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    void setMainPageProcessData(NavTreeIndex index, const MainPageProcessData& data)
    {
        MainPageProcessData dataCopy = data;
        if (dataCopy.currentStage < 0) {
            dataCopy.currentStage = 0;
        } else if (dataCopy.currentStage >= MAIN_PAGE_PROCESS_STAGE_COUNT) {
            dataCopy.currentStage = MAIN_PAGE_PROCESS_STAGE_COUNT - 1;
        }

        std::vector<MainPageProcessCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            m_mainPageProcessData[index] = dataCopy;
            callbacks.reserve(m_mainPageProcessCallbacks.size());
            for (const auto& entry : m_mainPageProcessCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    bool getMainPageProcessData(NavTreeIndex index, MainPageProcessData& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_mainPageProcessData.find(index);
        if (it == m_mainPageProcessData.end()) {
            return false;
        }
        out = it->second;
        return true;
    }

    void setMainPageVideoData(NavTreeIndex index, const MainPageVideoData& data)
    {
        MainPageVideoData dataCopy = data;
        std::vector<MainPageVideoCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            m_mainPageVideoData[index] = dataCopy;
            callbacks.reserve(m_mainPageVideoCallbacks.size());
            for (const auto& entry : m_mainPageVideoCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, &dataCopy, info.userData);
            }
        }
    }

    bool getMainPageVideoData(NavTreeIndex index, MainPageVideoData& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_mainPageVideoData.find(index);
        if (it == m_mainPageVideoData.end()) {
            return false;
        }
        out = it->second;
        return true;
    }

    void setVideoButtonDisplayMode(NavTreeIndex index, int mode)
    {
        QMutexLocker locker(&m_mutex);
        m_videoButtonDisplayMode[index] = mode;
    }

    bool getVideoButtonDisplayMode(NavTreeIndex index, int& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_videoButtonDisplayMode.find(index);
        if (it == m_videoButtonDisplayMode.end()) {
            return false;
        }
        out = it->second;
        return true;
    }

    bool getMainPageChartTableData(NavTreeIndex index, MainPageChartTableData& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_mainPageChartData.find(index);
        if (it == m_mainPageChartData.end()) {
            return false;
        }
        out = it->second.tableData;
        return true;
    }

    bool getMainPageOperStageData(NavTreeIndex index, MainPageOperStageData& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_mainPageOperStageData.find(index);
        if (it == m_mainPageOperStageData.end()) {
            return false;
        }
        out = it->second;
        return true;
    }

    bool getMainPageOperTotalData(NavTreeIndex index, MainPageOperTotalData& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_mainPageOperTotalData.find(index);
        if (it == m_mainPageOperTotalData.end()) {
            return false;
        }
        out = it->second;
        return true;
    }

    int registerWorkingConditionCallback(WorkingConditionCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        int id;
        std::vector<std::pair<NavTreeIndex, ConfigWorkingConditionData>> snapshot;
        {
            QMutexLocker locker(&m_mutex);
            id = m_nextCallbackId++;
            m_workingCallbacks[id] = {id, callback, userData};
            snapshot.reserve(m_workingConditionData.size());
            for (const auto& entry : m_workingConditionData) {
                snapshot.emplace_back(entry.first, entry.second);
            }
        }

        for (const auto& item : snapshot) {
            callback(item.first, &item.second, userData);
        }

        qDebug() << "Registered WorkingCondition callback, ID:" << id;
        return id;
    }

    int registerOxygenLanceCallback(OxygenLanceCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        int id;
        std::vector<std::pair<NavTreeIndex, ConfigOxygenLanceData>> snapshot;
        {
            QMutexLocker locker(&m_mutex);
            id = m_nextCallbackId++;
            m_oxygenCallbacks[id] = {id, callback, userData};
            snapshot.reserve(m_oxygenLanceData.size());
            for (const auto& entry : m_oxygenLanceData) {
                snapshot.emplace_back(entry.first, entry.second);
            }
        }

        for (const auto& item : snapshot) {
            callback(item.first, &item.second, userData);
        }

        qDebug() << "Registered OxygenLance callback, ID:" << id;
        return id;
    }

    int registerMaterialCallback(MaterialCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        int id;
        std::vector<std::pair<NavTreeIndex, ConfigMaterialData>> snapshot;
        {
            QMutexLocker locker(&m_mutex);
            id = m_nextCallbackId++;
            m_materialCallbacks[id] = {id, callback, userData};
            snapshot.reserve(m_materialData.size());
            for (const auto& entry : m_materialData) {
                snapshot.emplace_back(entry.first, entry.second);
            }
        }

        for (const auto& item : snapshot) {
            callback(item.first, &item.second, userData);
        }

        qDebug() << "Registered Material callback, ID:" << id;
        return id;
    }

    int registerMainPageWorkingConditionCallback(MainPageWorkingConditionCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        int id;
        std::vector<std::pair<NavTreeIndex, MainPageWorkingConditionData>> snapshot;
        {
            QMutexLocker locker(&m_mutex);
            id = m_nextCallbackId++;
            m_mainPageWorkingCallbacks[id] = {id, callback, userData};
            snapshot.reserve(m_mainPageWorkingConditionData.size());
            for (const auto& entry : m_mainPageWorkingConditionData) {
                snapshot.emplace_back(entry.first, entry.second);
            }
        }

        for (const auto& item : snapshot) {
            callback(item.first, &item.second, userData);
        }

        qDebug() << "Registered MainPage WorkingCondition callback, ID:" << id;
        return id;
    }

    int registerMainPageMaterialCallback(MainPageMaterialCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        int id;
        std::vector<std::pair<NavTreeIndex, MainPageMaterialData>> snapshot;
        {
            QMutexLocker locker(&m_mutex);
            id = m_nextCallbackId++;
            m_mainPageMaterialCallbacks[id] = {id, callback, userData};
            snapshot.reserve(m_mainPageMaterialData.size());
            for (const auto& entry : m_mainPageMaterialData) {
                snapshot.emplace_back(entry.first, entry.second);
            }
        }

        for (const auto& item : snapshot) {
            callback(item.first, &item.second, userData);
        }

        qDebug() << "Registered MainPage Material callback, ID:" << id;
        return id;
    }

    int registerMainPageOxygenLanceCallback(MainPageOxygenLanceCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        int id;
        std::vector<std::pair<NavTreeIndex, MainPageOxygenLanceData>> snapshot;
        {
            QMutexLocker locker(&m_mutex);
            id = m_nextCallbackId++;
            m_mainPageOxygenCallbacks[id] = {id, callback, userData};
            snapshot.reserve(m_mainPageOxygenLanceData.size());
            for (const auto& entry : m_mainPageOxygenLanceData) {
                snapshot.emplace_back(entry.first, entry.second);
            }
        }

        for (const auto& item : snapshot) {
            callback(item.first, &item.second, userData);
        }

        qDebug() << "Registered MainPage OxygenLance callback, ID:" << id;
        return id;
    }

    int registerMainPageBlowingCallback(MainPageBlowingCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        int id;
        std::vector<std::pair<NavTreeIndex, MainPageBlowingData>> snapshot;
        {
            QMutexLocker locker(&m_mutex);
            id = m_nextCallbackId++;
            m_mainPageBlowingCallbacks[id] = {id, callback, userData};
            snapshot.reserve(m_mainPageBlowingData.size());
            for (const auto& entry : m_mainPageBlowingData) {
                snapshot.emplace_back(entry.first, entry.second);
            }
        }

        for (const auto& item : snapshot) {
            callback(item.first, &item.second, userData);
        }

        qDebug() << "Registered MainPage Blowing callback, ID:" << id;
        return id;
    }

    int registerMainPageChartCallback(MainPageChartCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        int id;
        std::vector<std::pair<NavTreeIndex, MainPageChartData>> snapshot;
        {
            QMutexLocker locker(&m_mutex);
            id = m_nextCallbackId++;
            m_mainPageChartCallbacks[id] = {id, callback, userData};
            snapshot.reserve(m_mainPageChartData.size());
            for (const auto& entry : m_mainPageChartData) {
                snapshot.emplace_back(entry.first, entry.second);
            }
        }

        for (const auto& item : snapshot) {
            callback(item.first, &item.second, userData);
        }

        qDebug() << "Registered MainPage Chart callback, ID:" << id;
        return id;
    }

    int registerMainPageOperStageCallback(MainPageOperStageCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        int id;
        std::vector<std::pair<NavTreeIndex, MainPageOperStageData>> snapshot;
        {
            QMutexLocker locker(&m_mutex);
            id = m_nextCallbackId++;
            m_mainPageOperStageCallbacks[id] = {id, callback, userData};
            snapshot.reserve(m_mainPageOperStageData.size());
            for (const auto& entry : m_mainPageOperStageData) {
                snapshot.emplace_back(entry.first, entry.second);
            }
        }

        for (const auto& item : snapshot) {
            callback(item.first, &item.second, userData);
        }

        qDebug() << "Registered MainPage OperStage callback, ID:" << id;
        return id;
    }

    int registerMainPageOperTotalCallback(MainPageOperTotalCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        int id;
        std::vector<std::pair<NavTreeIndex, MainPageOperTotalData>> snapshot;
        {
            QMutexLocker locker(&m_mutex);
            id = m_nextCallbackId++;
            m_mainPageOperTotalCallbacks[id] = {id, callback, userData};
            snapshot.reserve(m_mainPageOperTotalData.size());
            for (const auto& entry : m_mainPageOperTotalData) {
                snapshot.emplace_back(entry.first, entry.second);
            }
        }

        for (const auto& item : snapshot) {
            callback(item.first, &item.second, userData);
        }

        qDebug() << "Registered MainPage OperTotal callback, ID:" << id;
        return id;
    }

    int registerMainPageProcessCallback(MainPageProcessCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        int id;
        std::vector<std::pair<NavTreeIndex, MainPageProcessData>> snapshot;
        {
            QMutexLocker locker(&m_mutex);
            id = m_nextCallbackId++;
            m_mainPageProcessCallbacks[id] = {id, callback, userData};
            snapshot.reserve(m_mainPageProcessData.size());
            for (const auto& entry : m_mainPageProcessData) {
                snapshot.emplace_back(entry.first, entry.second);
            }
        }

        for (const auto& item : snapshot) {
            callback(item.first, &item.second, userData);
        }

        qDebug() << "Registered MainPage Process callback, ID:" << id;
        return id;
    }

    int registerMainPageVideoCallback(MainPageVideoCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        int id;
        std::vector<std::pair<NavTreeIndex, MainPageVideoData>> snapshot;
        {
            QMutexLocker locker(&m_mutex);
            id = m_nextCallbackId++;
            m_mainPageVideoCallbacks[id] = {id, callback, userData};
            snapshot.reserve(m_mainPageVideoData.size());
            for (const auto& entry : m_mainPageVideoData) {
                snapshot.emplace_back(entry.first, entry.second);
            }
        }

        for (const auto& item : snapshot) {
            callback(item.first, &item.second, userData);
        }

        qDebug() << "Registered MainPage Video callback, ID:" << id;
        return id;
    }

    int registerMainPageVideoWindowHandleCallback(MainPageVideoWindowHandleCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        QMutexLocker locker(&m_mutex);
        int id = m_nextCallbackId++;
        m_mainPageVideoWindowHandleCallbacks[id] = {id, callback, userData};
        qDebug() << "Registered MainPage Video window handle callback, ID:" << id;
        return id;
    }

    void notifyVideoWindowHandleCallbacks(NavTreeIndex index, SteelClientWindowHandle handle)
    {
        std::vector<MainPageVideoWindowHandleCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            callbacks.reserve(m_mainPageVideoWindowHandleCallbacks.size());
            for (const auto& entry : m_mainPageVideoWindowHandleCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(index, handle, info.userData);
            }
        }
    }

    int registerApplicationShutdownCallback(ApplicationShutdownCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        QMutexLocker locker(&m_mutex);
        int id = m_nextCallbackId++;
        m_shutdownCallbacks[id] = {id, callback, userData};
        qDebug() << "Registered application shutdown callback, ID:" << id;
        return id;
    }

    void notifyApplicationShutdownCallbacks()
    {
        std::vector<ApplicationShutdownCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            callbacks.reserve(m_shutdownCallbacks.size());
            for (const auto& entry : m_shutdownCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(info.userData);
            }
        }
    }

    int registerDebugButtonCallback(DebugButtonCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        QMutexLocker locker(&m_mutex);
        int id = m_nextCallbackId++;
        m_debugButtonCallbacks[id] = {id, callback, userData};
        qDebug() << "Registered debug button callback, ID:" << id;
        return id;
    }

    void notifyDebugButtonCallbacks(int buttonType, bool isPressed)
    {
        std::vector<DebugButtonCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            callbacks.reserve(m_debugButtonCallbacks.size());
            for (const auto& entry : m_debugButtonCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        for (const auto& info : callbacks) {
            if (info.callback) {
                info.callback(buttonType, isPressed, info.userData);
            }
        }
    }

    bool unregisterCallback(int callbackId)
    {
        if (callbackId < 0) {
            return false;
        }

        QMutexLocker locker(&m_mutex);

        if (m_workingCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered WorkingCondition callback, ID:" << callbackId;
            return true;
        }
        if (m_oxygenCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered OxygenLance callback, ID:" << callbackId;
            return true;
        }
        if (m_materialCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered Material callback, ID:" << callbackId;
            return true;
        }
        if (m_loginCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered Login callback, ID:" << callbackId;
            return true;
        }
        if (m_mainPageWorkingCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered MainPage WorkingCondition callback, ID:" << callbackId;
            return true;
        }
        if (m_mainPageMaterialCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered MainPage Material callback, ID:" << callbackId;
            return true;
        }
        if (m_mainPageOxygenCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered MainPage OxygenLance callback, ID:" << callbackId;
            return true;
        }
        if (m_mainPageBlowingCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered MainPage Blowing callback, ID:" << callbackId;
            return true;
        }
        if (m_mainPageChartCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered MainPage Chart callback, ID:" << callbackId;
            return true;
        }
        if (m_mainPageOperStageCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered MainPage OperStage callback, ID:" << callbackId;
            return true;
        }
        if (m_mainPageOperTotalCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered MainPage OperTotal callback, ID:" << callbackId;
            return true;
        }
        if (m_mainPageProcessCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered MainPage Process callback, ID:" << callbackId;
            return true;
        }
        if (m_mainPageVideoCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered MainPage Video callback, ID:" << callbackId;
            return true;
        }
        if (m_mainPageVideoWindowHandleCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered MainPage Video window handle callback, ID:" << callbackId;
            return true;
        }
        if (m_shutdownCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered application shutdown callback, ID:" << callbackId;
            return true;
        }
        if (m_debugButtonCallbacks.erase(callbackId) > 0) {
            qDebug() << "Unregistered debug button callback, ID:" << callbackId;
            return true;
        }

        return false;
    }

    bool validateLogin(const char* username, const char* password, char* errorMessage, int errorMessageSize)
    {
        if (!username || !password) {
            return false;
        }

        std::vector<LoginCallbackInfo> callbacks;
        {
            QMutexLocker locker(&m_mutex);
            callbacks.reserve(m_loginCallbacks.size());
            for (const auto& entry : m_loginCallbacks) {
                callbacks.push_back(entry.second);
            }
        }

        // 如果没有注册回调，使用默认验证（向后兼容）
        if (callbacks.empty()) {
            // 默认验证逻辑（保持原有的硬编码验证）
            if (std::strcmp(username, "1") == 0 && std::strcmp(password, "1") == 0) {
                return true;
            }
            if (errorMessage && errorMessageSize > 0) {
                std::strncpy(errorMessage, "用户名或密码错误", errorMessageSize - 1);
                errorMessage[errorMessageSize - 1] = '\0';
            }
            return false;
        }

        // 调用所有注册的回调函数，只要有一个返回true就认为登录成功
        for (const auto& info : callbacks) {
            if (info.callback) {
                char localErrorMessage[256] = {0};
                bool result = info.callback(username, password, localErrorMessage, sizeof(localErrorMessage), info.userData);
                if (result) {
                    return true; // 登录成功
                }
                // 如果登录失败，保存错误消息（使用第一个非空错误消息）
                if (errorMessage && errorMessageSize > 0 && localErrorMessage[0] != '\0' && errorMessage[0] == '\0') {
                    std::strncpy(errorMessage, localErrorMessage, errorMessageSize - 1);
                    errorMessage[errorMessageSize - 1] = '\0';
                }
            }
        }

        // 所有回调都返回false，登录失败
        if (errorMessage && errorMessageSize > 0 && errorMessage[0] == '\0') {
            std::strncpy(errorMessage, "登录验证失败", errorMessageSize - 1);
            errorMessage[errorMessageSize - 1] = '\0';
        }
        return false;
    }

    int registerLoginCallback(LoginCallback callback, void* userData)
    {
        if (!callback) {
            return -1;
        }

        int id;
        {
            QMutexLocker locker(&m_mutex);
            id = m_nextCallbackId++;
            m_loginCallbacks[id] = {id, callback, userData};
        }

        qDebug() << "Registered Login callback, ID:" << id;
        return id;
    }

    bool getWorkingConditionData(NavTreeIndex index, ConfigWorkingConditionData& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_workingConditionData.find(index);
        if (it == m_workingConditionData.end()) {
            return false;
        }
        out = it->second;
        return true;
    }

    bool getFirstWorkingConditionData(NavTreeIndex& index, ConfigWorkingConditionData& out) const
    {
        QMutexLocker locker(&m_mutex);
        if (m_workingConditionData.empty()) {
            return false;
        }
        auto it = m_workingConditionData.begin();
        index = it->first;
        out = it->second;
        return true;
    }

    bool getOxygenLanceData(NavTreeIndex index, ConfigOxygenLanceData& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_oxygenLanceData.find(index);
        if (it == m_oxygenLanceData.end()) {
            return false;
        }
        out = it->second;
        return true;
    }

    bool getFirstOxygenLanceData(NavTreeIndex& index, ConfigOxygenLanceData& out) const
    {
        QMutexLocker locker(&m_mutex);
        if (m_oxygenLanceData.empty()) {
            return false;
        }
        auto it = m_oxygenLanceData.begin();
        index = it->first;
        out = it->second;
        return true;
    }

    bool getMaterialData(NavTreeIndex index, ConfigMaterialData& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_materialData.find(index);
        if (it == m_materialData.end()) {
            return false;
        }
        out = it->second;
        return true;
    }

    bool getFirstMaterialData(NavTreeIndex& index, ConfigMaterialData& out) const
    {
        QMutexLocker locker(&m_mutex);
        if (m_materialData.empty()) {
            return false;
        }
        auto it = m_materialData.begin();
        index = it->first;
        out = it->second;
        return true;
    }

    bool getMainPageWorkingConditionData(NavTreeIndex index, MainPageWorkingConditionData& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_mainPageWorkingConditionData.find(index);
        if (it == m_mainPageWorkingConditionData.end()) {
            return false;
        }
        out = it->second;
        return true;
    }

    bool getMainPageMaterialData(NavTreeIndex index, MainPageMaterialData& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_mainPageMaterialData.find(index);
        if (it == m_mainPageMaterialData.end()) {
            return false;
        }
        out = it->second;
        return true;
    }

    bool getMainPageOxygenLanceData(NavTreeIndex index, MainPageOxygenLanceData& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_mainPageOxygenLanceData.find(index);
        if (it == m_mainPageOxygenLanceData.end()) {
            return false;
        }
        out = it->second;
        return true;
    }

    bool getMainPageBlowingData(NavTreeIndex index, MainPageBlowingData& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_mainPageBlowingData.find(index);
        if (it == m_mainPageBlowingData.end()) {
            return false;
        }
        out = it->second;
        return true;
    }

    bool getMainPageChartData(NavTreeIndex index, MainPageChartData& out) const
    {
        QMutexLocker locker(&m_mutex);
        auto it = m_mainPageChartData.find(index);
        if (it == m_mainPageChartData.end()) {
            return false;
        }
        out = it->second;
        return true;
    }

private:
    APIDataManager() = default;

    mutable QMutex m_mutex;
    int m_nextCallbackId = 1;

    std::map<NavTreeIndex, ConfigWorkingConditionData> m_workingConditionData;
    std::map<NavTreeIndex, ConfigOxygenLanceData> m_oxygenLanceData;
    std::map<NavTreeIndex, ConfigMaterialData> m_materialData;
    std::map<NavTreeIndex, MainPageWorkingConditionData> m_mainPageWorkingConditionData;
    std::map<NavTreeIndex, MainPageMaterialData> m_mainPageMaterialData;
    std::map<NavTreeIndex, MainPageOxygenLanceData> m_mainPageOxygenLanceData;
    std::map<NavTreeIndex, MainPageBlowingData> m_mainPageBlowingData;
    std::map<NavTreeIndex, MainPageChartData> m_mainPageChartData;
    std::map<NavTreeIndex, MainPageOperStageData> m_mainPageOperStageData;
    std::map<NavTreeIndex, MainPageOperTotalData> m_mainPageOperTotalData;
    std::map<NavTreeIndex, MainPageProcessData> m_mainPageProcessData;
    std::map<NavTreeIndex, MainPageVideoData> m_mainPageVideoData;
    std::map<NavTreeIndex, int> m_videoButtonDisplayMode; // 存储每个炉子的按钮显示模式

    std::map<int, WorkingConditionCallbackInfo> m_workingCallbacks;
    std::map<int, OxygenLanceCallbackInfo> m_oxygenCallbacks;
    std::map<int, MaterialCallbackInfo> m_materialCallbacks;
    std::map<int, LoginCallbackInfo> m_loginCallbacks;
    std::map<int, MainPageWorkingConditionCallbackInfo> m_mainPageWorkingCallbacks;
    std::map<int, MainPageMaterialCallbackInfo> m_mainPageMaterialCallbacks;
    std::map<int, MainPageOxygenLanceCallbackInfo> m_mainPageOxygenCallbacks;
    std::map<int, MainPageBlowingCallbackInfo> m_mainPageBlowingCallbacks;
    std::map<int, MainPageChartCallbackInfo> m_mainPageChartCallbacks;
    std::map<int, MainPageOperStageCallbackInfo> m_mainPageOperStageCallbacks;
    std::map<int, MainPageOperTotalCallbackInfo> m_mainPageOperTotalCallbacks;
    std::map<int, MainPageProcessCallbackInfo> m_mainPageProcessCallbacks;
    std::map<int, MainPageVideoCallbackInfo> m_mainPageVideoCallbacks;
    std::map<int, MainPageVideoWindowHandleCallbackInfo> m_mainPageVideoWindowHandleCallbacks;
    std::map<int, ApplicationShutdownCallbackInfo> m_shutdownCallbacks;
    std::map<int, DebugButtonCallbackInfo> m_debugButtonCallbacks;
};

SteelClientWindowHandle fetchVideoWindowHandle()
{
    if (!g_mainWindow) {
        qWarning() << "fetchVideoWindowHandle: main window not initialized";
        return 0;
    }

    MainPageWidget* mainPageWidget = g_mainWindow->getMainPageWidget();
    if (!mainPageWidget) {
        qWarning() << "fetchVideoWindowHandle: main page widget not available";
        return 0;
    }

    WId handle = mainPageWidget->getVideoWindowHandle();
    if (!handle) {
        qWarning() << "fetchVideoWindowHandle: video window handle not ready";
    }

    return static_cast<SteelClientWindowHandle>(handle);
}

void notifyVideoWindowHandleForAllNavs()
{
    SteelClientWindowHandle handle = fetchVideoWindowHandle();
    if (!handle) {
        return;
    }

    const NavTreeIndex navIndices[] = {Main_1, Main_2, Main_3, Main_4, Main_5, Main_6};

    for (NavTreeIndex index : navIndices) {
        APIDataManager::instance().notifyVideoWindowHandleCallbacks(index, handle);
    }
}

void requestVideoWindowHandleNotification()
{
    MainWindow* mainWindow = g_mainWindow;
    if (!mainWindow) {
        return;
    }

    QMetaObject::invokeMethod(mainWindow, []() {
        notifyVideoWindowHandleForAllNavs();
    }, Qt::QueuedConnection);
}

} // namespace

// 在匿名命名空间外定义，以便其他文件可以访问
void notifyDebugButtonCallbacks(int buttonType, bool isPressed)
{
    APIDataManager::instance().notifyDebugButtonCallbacks(buttonType, isPressed);
}

namespace SteelClientData {

bool getWorkingConditionData(NavTreeIndex index, ConfigWorkingConditionData& out)
{
    return APIDataManager::instance().getWorkingConditionData(index, out);
}

bool getFirstWorkingConditionData(NavTreeIndex& index, ConfigWorkingConditionData& out)
{
    return APIDataManager::instance().getFirstWorkingConditionData(index, out);
}

bool getOxygenLanceData(NavTreeIndex index, ConfigOxygenLanceData& out)
{
    return APIDataManager::instance().getOxygenLanceData(index, out);
}

bool getFirstOxygenLanceData(NavTreeIndex& index, ConfigOxygenLanceData& out)
{
    return APIDataManager::instance().getFirstOxygenLanceData(index, out);
}

bool getMaterialData(NavTreeIndex index, ConfigMaterialData& out)
{
    return APIDataManager::instance().getMaterialData(index, out);
}

bool getFirstMaterialData(NavTreeIndex& index, ConfigMaterialData& out)
{
    return APIDataManager::instance().getFirstMaterialData(index, out);
}

void setWorkingConditionData(NavTreeIndex index, const ConfigWorkingConditionData& data)
{
    APIDataManager::instance().setWorkingConditionData(index, data);
}

void setOxygenLanceData(NavTreeIndex index, const ConfigOxygenLanceData& data)
{
    APIDataManager::instance().setOxygenLanceData(index, data);
}

void setMaterialData(NavTreeIndex index, const ConfigMaterialData& data)
{
    APIDataManager::instance().setMaterialData(index, data);
}

bool getMainPageWorkingConditionData(NavTreeIndex index, MainPageWorkingConditionData& out)
{
    return APIDataManager::instance().getMainPageWorkingConditionData(index, out);
}

void setMainPageWorkingConditionData(NavTreeIndex index, const MainPageWorkingConditionData& data)
{
    APIDataManager::instance().setMainPageWorkingConditionData(index, data);
}

bool getMainPageMaterialData(NavTreeIndex index, MainPageMaterialData& out)
{
    return APIDataManager::instance().getMainPageMaterialData(index, out);
}

void setMainPageMaterialData(NavTreeIndex index, const MainPageMaterialData& data)
{
    APIDataManager::instance().setMainPageMaterialData(index, data);
}

void setMainPageWorkingConditionItem(NavTreeIndex index, int itemIndex, const char* name, const char* value)
{
    APIDataManager::instance().setMainPageWorkingConditionItem(index, itemIndex, name, value);
}

void setMainPageMaterialItem(NavTreeIndex index, int itemIndex, const char* name, const char* value)
{
    APIDataManager::instance().setMainPageMaterialItem(index, itemIndex, name, value);
}

bool getMainPageOxygenLanceData(NavTreeIndex index, MainPageOxygenLanceData& out)
{
    return APIDataManager::instance().getMainPageOxygenLanceData(index, out);
}

void setMainPageOxygenLanceData(NavTreeIndex index, const MainPageOxygenLanceData& data)
{
    APIDataManager::instance().setMainPageOxygenLanceData(index, data);
}

void setMainPageOxygenLanceField(NavTreeIndex index, const char* fieldName, double value)
{
    APIDataManager::instance().setMainPageOxygenLanceField(index, fieldName, value);
}

bool getMainPageBlowingData(NavTreeIndex index, MainPageBlowingData& out)
{
    return APIDataManager::instance().getMainPageBlowingData(index, out);
}

void setMainPageBlowingData(NavTreeIndex index, const MainPageBlowingData& data)
{
    APIDataManager::instance().setMainPageBlowingData(index, data);
}

void setMainPageBlowingField(NavTreeIndex index, const char* fieldName, const char* value)
{
    APIDataManager::instance().setMainPageBlowingField(index, fieldName, value);
}

bool getMainPageChartData(NavTreeIndex index, MainPageChartData& out)
{
    return APIDataManager::instance().getMainPageChartData(index, out);
}

void setMainPageChartTableData(NavTreeIndex index, const MainPageChartTableData& data)
{
    APIDataManager::instance().setMainPageChartTableData(index, data);
}

void setMainPageChartTableItem(NavTreeIndex index, int row, int column, const char* value)
{
    APIDataManager::instance().setMainPageChartTableItem(index, row, column, value);
}

bool getMainPageChartTableData(NavTreeIndex index, MainPageChartTableData& out)
{
    return APIDataManager::instance().getMainPageChartTableData(index, out);
}

void setMainPageChartData(NavTreeIndex index, const MainPageChartData& data)
{
    APIDataManager::instance().setMainPageChartData(index, data);
}

bool getMainPageOperStageData(NavTreeIndex index, MainPageOperStageData& out)
{
    return APIDataManager::instance().getMainPageOperStageData(index, out);
}

void setMainPageOperStageData(NavTreeIndex index, const MainPageOperStageData& data)
{
    APIDataManager::instance().setMainPageOperStageData(index, data);
}

void setMainPageOperStageItem(NavTreeIndex index, int row, int column, const char* value)
{
    APIDataManager::instance().setMainPageOperStageItem(index, row, column, value);
}

bool getMainPageOperTotalData(NavTreeIndex index, MainPageOperTotalData& out)
{
    return APIDataManager::instance().getMainPageOperTotalData(index, out);
}

void setMainPageOperTotalData(NavTreeIndex index, const MainPageOperTotalData& data)
{
    APIDataManager::instance().setMainPageOperTotalData(index, data);
}

void setMainPageOperTotalItem(NavTreeIndex index, int row, int column, const char* value)
{
    APIDataManager::instance().setMainPageOperTotalItem(index, row, column, value);
}

bool getMainPageProcessData(NavTreeIndex index, MainPageProcessData& out)
{
    return APIDataManager::instance().getMainPageProcessData(index, out);
}

void setMainPageProcessData(NavTreeIndex index, const MainPageProcessData& data)
{
    APIDataManager::instance().setMainPageProcessData(index, data);
}

bool getMainPageVideoData(NavTreeIndex index, MainPageVideoData& out)
{
    return APIDataManager::instance().getMainPageVideoData(index, out);
}

void setMainPageVideoData(NavTreeIndex index, const MainPageVideoData& data)
{
    APIDataManager::instance().setMainPageVideoData(index, data);
}

bool getVideoButtonDisplayMode(NavTreeIndex index, int& out)
{
    return APIDataManager::instance().getVideoButtonDisplayMode(index, out);
}

bool validateLogin(const char* username, const char* password, char* errorMessage, int errorMessageSize)
{
    return APIDataManager::instance().validateLogin(username, password, errorMessage, errorMessageSize);
}

void notifyApplicationShutdown()
{
    APIDataManager::instance().notifyApplicationShutdownCallbacks();
}

} // namespace SteelClientData

extern "C" {

STEELCLIENT_API int startUI(int argc, char* argv[], const char* configJson)
{
    try {
    QApplication app(argc, argv);
    
    app.setApplicationName("智慧炼钢系统");
    app.setApplicationVersion("1.0.0");
    app.setOrganizationName("SteelClient");
    
    app.setStyle(QStyleFactory::create("Fusion"));
    
    QPalette darkPalette;
    darkPalette.setColor(QPalette::Window, QColor(30, 58, 95));
    darkPalette.setColor(QPalette::WindowText, Qt::white);
    darkPalette.setColor(QPalette::Base, QColor(30, 58, 95));
    darkPalette.setColor(QPalette::AlternateBase, QColor(45, 191, 255));
    darkPalette.setColor(QPalette::ToolTipBase, Qt::white);
    darkPalette.setColor(QPalette::ToolTipText, Qt::white);
    darkPalette.setColor(QPalette::Text, Qt::white);
    darkPalette.setColor(QPalette::Button, QColor(30, 58, 95));
    darkPalette.setColor(QPalette::ButtonText, Qt::white);
    darkPalette.setColor(QPalette::BrightText, Qt::red);
    darkPalette.setColor(QPalette::Link, QColor(45, 191, 255));
    darkPalette.setColor(QPalette::Highlight, QColor(43, 128, 255));
    darkPalette.setColor(QPalette::HighlightedText, Qt::white);
    app.setPalette(darkPalette);
    
    QFont font("Microsoft YaHei", 9);
    app.setFont(font);
    
    StyleManager::loadGlobalStyle(&app);
    
        if (configJson && std::strlen(configJson) > 0) {
            QByteArray jsonData(configJson);
            QJsonParseError parseError;
            QJsonDocument doc = QJsonDocument::fromJson(jsonData, &parseError);
            if (parseError.error != QJsonParseError::NoError) {
                qWarning() << "Failed to parse configJson:" << parseError.errorString();
            } else if (doc.isObject()) {
                QJsonObject root = doc.object();

                auto readGroup = [](const QJsonObject& obj, const char* key, auto setter) {
                    if (obj.contains(key) && obj.value(key).isObject()) {
                        setter(obj.value(key).toObject());
                    }
                };

                auto processWorkingCondition = [&](const QJsonObject& workingObj) {
                    ConfigWorkingConditionData working;
                    NavTreeIndex workingIndex = NavTreeIndex::Config_1;
                    if (workingObj.contains("index")) {
                        workingIndex = static_cast<NavTreeIndex>(workingObj.value("index").toInt(static_cast<int>(workingIndex)));
                    }

                    readGroup(workingObj, "moltenIron", [&](const QJsonObject& objGroup) {
                        working.moltenIron.Mn = objGroup.value("mn").toDouble(working.moltenIron.Mn);
                        working.moltenIron.P = objGroup.value("p").toDouble(working.moltenIron.P);
                        working.moltenIron.S = objGroup.value("s").toDouble(working.moltenIron.S);
                        working.moltenIron.Ti = objGroup.value("ti").toDouble(working.moltenIron.Ti);
                        working.moltenIron.other = objGroup.value("other").toDouble(working.moltenIron.other);
                    });

                    readGroup(workingObj, "target", [&](const QJsonObject& objGroup) {
                        working.target.C = objGroup.value("c").toDouble(working.target.C);
                        working.target.Si = objGroup.value("si").toDouble(working.target.Si);
                        working.target.Mn = objGroup.value("mn").toDouble(working.target.Mn);
                        working.target.P = objGroup.value("p").toDouble(working.target.P);
                        working.target.S = objGroup.value("s").toDouble(working.target.S);
                        working.target.T = objGroup.value("t").toDouble(working.target.T);
                    });

                    readGroup(workingObj, "scrapSteel", [&](const QJsonObject& objGroup) {
                        working.scrapSteel.C = objGroup.value("c").toDouble(working.scrapSteel.C);
                        working.scrapSteel.Si = objGroup.value("si").toDouble(working.scrapSteel.Si);
                        working.scrapSteel.Mn = objGroup.value("mn").toDouble(working.scrapSteel.Mn);
                        working.scrapSteel.oxidation = objGroup.value("oxidation").toDouble(working.scrapSteel.oxidation);
                    });

                    readGroup(workingObj, "chuteFlow", [&](const QJsonObject& objGroup) {
                        working.chuteFlow.normal = objGroup.value("normal").toDouble(working.chuteFlow.normal);
                        working.chuteFlow.retain = objGroup.value("retain").toDouble(working.chuteFlow.retain);
                        working.chuteFlow.total = objGroup.value("total").toDouble(working.chuteFlow.total);
                        working.chuteFlow.more = objGroup.value("more").toDouble(working.chuteFlow.more);
                        working.chuteFlow.less = objGroup.value("less").toDouble(working.chuteFlow.less);
                        working.chuteFlow.none = objGroup.value("none").toDouble(working.chuteFlow.none);
                    });

                    if (isValidNavTreeIndex(workingIndex)) {
                        APIDataManager::instance().setWorkingConditionData(workingIndex, working);
                        qDebug() << "Loaded working condition data from configJson for index" << static_cast<int>(workingIndex);
                    } else {
                        qWarning() << "Invalid working condition index in configJson:" << static_cast<int>(workingIndex);
                    }
                };

                if (root.contains("working_condition")) {
                    QJsonValue value = root.value("working_condition");
                    if (value.isArray()) {
                        for (const QJsonValue& item : value.toArray()) {
                            if (item.isObject()) {
                                processWorkingCondition(item.toObject());
                            }
                        }
                    } else if (value.isObject()) {
                        processWorkingCondition(value.toObject());
                    }
                }

                auto processOxygenLance = [&](const QJsonObject& oxygenObj) {
                    ConfigOxygenLanceData oxygen;
                    NavTreeIndex oxygenIndex = NavTreeIndex::Main_1;
                    if (oxygenObj.contains("index")) {
                        oxygenIndex = static_cast<NavTreeIndex>(oxygenObj.value("index").toInt(static_cast<int>(oxygenIndex)));
                    }

                    if (oxygenObj.contains("lanceDivision")) {
                        const QJsonValue value = oxygenObj.value("lanceDivision");
                        if (value.isArray()) {
                            QJsonArray arr = value.toArray();
                            for (int i = 0; i < 6; ++i) {
                                if (i < arr.size()) {
                                    oxygen.lanceDivision[i] = arr.at(i).toDouble(oxygen.lanceDivision[i]);
                                }
                            }
                        }
                    }

                    oxygen.postBlowOxygenUtilization = oxygenObj.value("postBlowOxygenUtilization").toDouble(oxygen.postBlowOxygenUtilization);

                    readGroup(oxygenObj, "initialOxygenFactor", [&](const QJsonObject& objGroup) {
                        oxygen.initialOxygenFactor.A = objGroup.value("a").toDouble(oxygen.initialOxygenFactor.A);
                        oxygen.initialOxygenFactor.B = objGroup.value("b").toDouble(oxygen.initialOxygenFactor.B);
                    });

                    oxygen.actualOxygenFlow = oxygenObj.value("actualOxygenFlow").toDouble(oxygen.actualOxygenFlow);
                    oxygen.sinteredOreGrade = oxygenObj.value("sinteredOreGrade").toDouble(oxygen.sinteredOreGrade);
                    oxygen.cokeBreezeCarbonContent = oxygenObj.value("cokeBreezeCarbonContent").toDouble(oxygen.cokeBreezeCarbonContent);
                    oxygen.limestoneCO2Content = oxygenObj.value("limestoneCO2Content").toDouble(oxygen.limestoneCO2Content);

                    readGroup(oxygenObj, "oxygenSupply", [&](const QJsonObject& objGroup) {
                        oxygen.oxygenSupply.sinter = objGroup.value("sinter").toDouble(oxygen.oxygenSupply.sinter);
                        oxygen.oxygenSupply.steel = objGroup.value("steel").toDouble(oxygen.oxygenSupply.steel);
                        oxygen.oxygenSupply.coke = objGroup.value("coke").toDouble(oxygen.oxygenSupply.coke);
                        oxygen.oxygenSupply.limestone = objGroup.value("limestone").toDouble(oxygen.oxygenSupply.limestone);
                    });

                    oxygen.adjustMoltenIronCUpperLimit = oxygenObj.value("adjustMoltenIronCUpperLimit").toDouble(oxygen.adjustMoltenIronCUpperLimit);
                    oxygen.adjustmentRatio = oxygenObj.value("adjustmentRatio").toDouble(oxygen.adjustmentRatio);

                    if (isValidNavTreeIndex(oxygenIndex)) {
                        APIDataManager::instance().setOxygenLanceData(oxygenIndex, oxygen);
                        qDebug() << "Loaded oxygen lance data from configJson for index" << static_cast<int>(oxygenIndex);
                    } else {
                        qWarning() << "Invalid oxygen lance index in configJson:" << static_cast<int>(oxygenIndex);
                    }
                };

                if (root.contains("oxygen_lance")) {
                    QJsonValue value = root.value("oxygen_lance");
                    if (value.isArray()) {
                        for (const QJsonValue& item : value.toArray()) {
                            if (item.isObject()) {
                                processOxygenLance(item.toObject());
                            }
                        }
                    } else if (value.isObject()) {
                        processOxygenLance(value.toObject());
                    }
                }

                auto processMaterial = [&](const QJsonObject& materialObj) {
                    ConfigMaterialData material;
                    NavTreeIndex materialIndex = NavTreeIndex::Trace_1;
                    if (materialObj.contains("index")) {
                        materialIndex = static_cast<NavTreeIndex>(materialObj.value("index").toInt(static_cast<int>(materialIndex)));
                    }

                    if (materialObj.contains("feedingMode") && materialObj.value("feedingMode").isObject()) {
                        QJsonObject fm = materialObj.value("feedingMode").toObject();
                        material.feedingMode.mode = fm.value("mode").toInt(material.feedingMode.mode);
                        material.feedingMode.csjk = fm.value("csjk").toDouble(material.feedingMode.csjk);
                        material.feedingMode.gsjk = fm.value("gsjk").toDouble(material.feedingMode.gsjk);
                    }

                    if (isValidNavTreeIndex(materialIndex)) {
                        APIDataManager::instance().setMaterialData(materialIndex, material);
                        qDebug() << "Loaded material data from configJson for index" << static_cast<int>(materialIndex);
                    } else {
                        qWarning() << "Invalid material index in configJson:" << static_cast<int>(materialIndex);
                    }
                };

                if (root.contains("material")) {
                    QJsonValue value = root.value("material");
                    if (value.isArray()) {
                        for (const QJsonValue& item : value.toArray()) {
                            if (item.isObject()) {
                                processMaterial(item.toObject());
                            }
                        }
                    } else if (value.isObject()) {
                        processMaterial(value.toObject());
                    }
                }

                auto processMainWorking = [&](const QJsonObject& mainWorkingObj) {
                    MainPageWorkingConditionData working{};
                    NavTreeIndex workingIndex = NavTreeIndex::Main_1;
                    if (mainWorkingObj.contains("index")) {
                        workingIndex = static_cast<NavTreeIndex>(mainWorkingObj.value("index").toInt(static_cast<int>(workingIndex)));
                    }

                    if (mainWorkingObj.contains("items") && mainWorkingObj.value("items").isArray()) {
                        QJsonArray itemsArray = mainWorkingObj.value("items").toArray();
                        working.count = std::min<int>(itemsArray.size(), MAIN_PAGE_WORKING_MAX_ITEMS);
                        for (int i = 0; i < working.count; ++i) {
                            if (!itemsArray.at(i).isObject()) {
                                continue;
                            }
                            QJsonObject itemObj = itemsArray.at(i).toObject();
                            QString name = itemObj.value("name").toString();
                            QString value = itemObj.value("value").toString();
                            QByteArray nameBytes = name.toUtf8();
                            QByteArray valueBytes = value.toUtf8();
                            std::strncpy(working.items[i].name, nameBytes.constData(), sizeof(working.items[i].name) - 1);
                            working.items[i].name[sizeof(working.items[i].name) - 1] = '\0';
                            std::strncpy(working.items[i].value, valueBytes.constData(), sizeof(working.items[i].value) - 1);
                            working.items[i].value[sizeof(working.items[i].value) - 1] = '\0';
                        }
                    }

                    if (isValidNavTreeIndex(workingIndex)) {
                        APIDataManager::instance().setMainPageWorkingConditionData(workingIndex, working);
                        qDebug() << "Loaded main page working data from configJson for index" << static_cast<int>(workingIndex);
                    } else {
                        qWarning() << "Invalid main page working index in configJson:" << static_cast<int>(workingIndex);
                    }
                };

                auto processMainMaterial = [&](const QJsonObject& mainMaterialObj) {
                    MainPageMaterialData material{};
                    NavTreeIndex materialIndex = NavTreeIndex::Main_1;
                    if (mainMaterialObj.contains("index")) {
                        materialIndex = static_cast<NavTreeIndex>(mainMaterialObj.value("index").toInt(static_cast<int>(materialIndex)));
                    }

                    if (mainMaterialObj.contains("items") && mainMaterialObj.value("items").isArray()) {
                        QJsonArray itemsArray = mainMaterialObj.value("items").toArray();
                        material.count = std::min<int>(itemsArray.size(), MAIN_PAGE_MATERIAL_MAX_ITEMS);
                        for (int i = 0; i < material.count; ++i) {
                            if (!itemsArray.at(i).isObject()) {
                                continue;
                            }
                            QJsonObject itemObj = itemsArray.at(i).toObject();
                            QString name = itemObj.value("name").toString();
                            QString value = itemObj.value("value").toString();
                            QByteArray nameBytes = name.toUtf8();
                            QByteArray valueBytes = value.toUtf8();
                            std::strncpy(material.items[i].name, nameBytes.constData(), sizeof(material.items[i].name) - 1);
                            material.items[i].name[sizeof(material.items[i].name) - 1] = '\0';
                            std::strncpy(material.items[i].value, valueBytes.constData(), sizeof(material.items[i].value) - 1);
                            material.items[i].value[sizeof(material.items[i].value) - 1] = '\0';
                        }
                    }

                    if (isValidNavTreeIndex(materialIndex)) {
                        APIDataManager::instance().setMainPageMaterialData(materialIndex, material);
                        qDebug() << "Loaded main page material data from configJson for index" << static_cast<int>(materialIndex);
                    } else {
                        qWarning() << "Invalid main page material index in configJson:" << static_cast<int>(materialIndex);
                    }
                };

                auto processMainOxygen = [&](const QJsonObject& mainOxygenObj) {
                    MainPageOxygenLanceData oxygen{};
                    NavTreeIndex oxygenIndex = NavTreeIndex::Main_1;
                    if (mainOxygenObj.contains("index")) {
                        oxygenIndex = static_cast<NavTreeIndex>(mainOxygenObj.value("index").toInt(static_cast<int>(oxygenIndex)));
                    }

                    oxygen.oxygenFlow = mainOxygenObj.value("oxygenFlow").toDouble(oxygen.oxygenFlow);
                    oxygen.lanceHeight = mainOxygenObj.value("lanceHeight").toDouble(oxygen.lanceHeight);
                    oxygen.readingBlowQuantity = mainOxygenObj.value("readingBlow").toDouble(oxygen.readingBlowQuantity);
                    oxygen.accumulatedBlowQuantity = mainOxygenObj.value("accumulatedBlow").toDouble(oxygen.accumulatedBlowQuantity);
                    oxygen.converterAngle = mainOxygenObj.value("converterAngle").toDouble(oxygen.converterAngle);
                    oxygen.oxygenPressure = mainOxygenObj.value("oxygenPressure").toDouble(oxygen.oxygenPressure);

                    if (isValidNavTreeIndex(oxygenIndex)) {
                        APIDataManager::instance().setMainPageOxygenLanceData(oxygenIndex, oxygen);
                        qDebug() << "Loaded main page oxygen lance data from configJson for index" << static_cast<int>(oxygenIndex);
                    } else {
                        qWarning() << "Invalid main page oxygen index in configJson:" << static_cast<int>(oxygenIndex);
                    }
                };

                if (root.contains("main_working_condition")) {
                    QJsonValue value = root.value("main_working_condition");
                    if (value.isArray()) {
                        for (const QJsonValue &item : value.toArray()) {
                            if (item.isObject()) {
                                processMainWorking(item.toObject());
                            }
                        }
                    } else if (value.isObject()) {
                        processMainWorking(value.toObject());
                    }
                }

                if (root.contains("main_material")) {
                    QJsonValue value = root.value("main_material");
                    if (value.isArray()) {
                        for (const QJsonValue &item : value.toArray()) {
                            if (item.isObject()) {
                                processMainMaterial(item.toObject());
                            }
                        }
                    } else if (value.isObject()) {
                        processMainMaterial(value.toObject());
                    }
                }

                if (root.contains("main_oxygen_lance")) {
                    QJsonValue value = root.value("main_oxygen_lance");
                    if (value.isArray()) {
                        for (const QJsonValue &item : value.toArray()) {
                            if (item.isObject()) {
                                processMainOxygen(item.toObject());
                            }
                        }
                    } else if (value.isObject()) {
                        processMainOxygen(value.toObject());
                    }
                }

                if (root.contains("main_blowing")) {
                    QJsonValue value = root.value("main_blowing");
                    auto processValue = [&](const QJsonObject &obj) {
                        MainPageBlowingData blowing{};
                        NavTreeIndex blowingIndex = NavTreeIndex::Main_1;
                        if (obj.contains("index")) {
                            blowingIndex = static_cast<NavTreeIndex>(obj.value("index").toInt(static_cast<int>(blowingIndex)));
                        }

                        auto copyString = [](char *dest, size_t size, const QString &text) {
                            QByteArray bytes = text.toUtf8();
                            std::strncpy(dest, bytes.constData(), size - 1);
                            dest[size - 1] = '\0';
                        };

                        copyString(blowing.currentBlowingTime, sizeof(blowing.currentBlowingTime), obj.value("currentTime").toString());
                        copyString(blowing.estimatedRemainingTime, sizeof(blowing.estimatedRemainingTime), obj.value("remainingTime").toString());
                        copyString(blowing.currentTemperature, sizeof(blowing.currentTemperature), obj.value("temperature").toString());
                        copyString(blowing.currentCarbonContent, sizeof(blowing.currentCarbonContent), obj.value("carbonContent").toString());
                        copyString(blowing.operatingMode, sizeof(blowing.operatingMode), obj.value("operatingMode").toString());

                        if (isValidNavTreeIndex(blowingIndex)) {
                            APIDataManager::instance().setMainPageBlowingData(blowingIndex, blowing);
                            qDebug() << "Loaded main page blowing data from configJson for index" << static_cast<int>(blowingIndex);
                        } else {
                            qWarning() << "Invalid main page blowing index in configJson:" << static_cast<int>(blowingIndex);
                        }
                    };

                    if (value.isArray()) {
                        for (const QJsonValue &item : value.toArray()) {
                            if (item.isObject()) {
                                processValue(item.toObject());
                            }
                        }
                    } else if (value.isObject()) {
                        processValue(value.toObject());
                    }
                }
            }
        }

    MainWindow window;
    g_mainWindow = &window;
    window.show();
    requestVideoWindowHandleNotification();
    
        qDebug() << "SteelClient UI started";

    int result = app.exec();
    
        qDebug() << "SteelClient UI exited with code" << result;
    g_mainWindow = nullptr;
    return result;
    } catch (const std::exception& ex) {
        qCritical() << "startUI exception:" << ex.what();
        return -1;
    } catch (...) {
        qCritical() << "startUI unknown exception";
        return -1;
    }
}

STEELCLIENT_API int registerWorkingConditionCallback(WorkingConditionCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerWorkingConditionCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerWorkingConditionCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerOxygenLanceCallback(OxygenLanceCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerOxygenLanceCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerOxygenLanceCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerMaterialCallback(MaterialCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerMaterialCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerMaterialCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerMainPageWorkingConditionCallback(MainPageWorkingConditionCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerMainPageWorkingConditionCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerMainPageWorkingConditionCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerMainPageMaterialCallback(MainPageMaterialCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerMainPageMaterialCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerMainPageMaterialCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerMainPageOxygenLanceCallback(MainPageOxygenLanceCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerMainPageOxygenLanceCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerMainPageOxygenLanceCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerMainPageBlowingCallback(MainPageBlowingCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerMainPageBlowingCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerMainPageBlowingCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerMainPageChartCallback(MainPageChartCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerMainPageChartCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerMainPageChartCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerMainPageOperStageCallback(MainPageOperStageCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerMainPageOperStageCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerMainPageOperStageCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerMainPageOperTotalCallback(MainPageOperTotalCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerMainPageOperTotalCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerMainPageOperTotalCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerMainPageProcessCallback(MainPageProcessCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerMainPageProcessCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerMainPageProcessCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerMainPageVideoCallback(MainPageVideoCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerMainPageVideoCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerMainPageVideoCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerMainPageVideoWindowHandleCallback(MainPageVideoWindowHandleCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerMainPageVideoWindowHandleCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerMainPageVideoWindowHandleCallback failed";
        return id;
    }
    requestVideoWindowHandleNotification();
    return id;
}

STEELCLIENT_API int registerApplicationShutdownCallback(ApplicationShutdownCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerApplicationShutdownCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerApplicationShutdownCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerDebugButtonCallback(DebugButtonCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerDebugButtonCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerDebugButtonCallback failed";
    }
    return id;
}

STEELCLIENT_API int registerLoginCallback(LoginCallback callback, void* userData)
{
    int id = APIDataManager::instance().registerLoginCallback(callback, userData);
    if (id < 0) {
        qWarning() << "registerLoginCallback failed";
    }
    return id;
}

STEELCLIENT_API void setMainPageWorkingConditionData(NavTreeIndex index, const MainPageWorkingConditionData& data)
{
    SteelClientData::setMainPageWorkingConditionData(index, data);
}

STEELCLIENT_API bool getMainPageWorkingConditionData(NavTreeIndex index, MainPageWorkingConditionData& out)
{
    return SteelClientData::getMainPageWorkingConditionData(index, out);
}

STEELCLIENT_API void setMainPageMaterialData(NavTreeIndex index, const MainPageMaterialData& data)
{
    SteelClientData::setMainPageMaterialData(index, data);
}

STEELCLIENT_API bool getMainPageMaterialData(NavTreeIndex index, MainPageMaterialData& out)
{
    return SteelClientData::getMainPageMaterialData(index, out);
}

STEELCLIENT_API void setMainPageWorkingConditionItem(NavTreeIndex index, int itemIndex, const char* name, const char* value)
{
    SteelClientData::setMainPageWorkingConditionItem(index, itemIndex, name, value);
}

STEELCLIENT_API void setMainPageMaterialItem(NavTreeIndex index, int itemIndex, const char* name, const char* value)
{
    SteelClientData::setMainPageMaterialItem(index, itemIndex, name, value);
}

STEELCLIENT_API void setMainPageOxygenLanceData(NavTreeIndex index, const MainPageOxygenLanceData& data)
{
    SteelClientData::setMainPageOxygenLanceData(index, data);
}

STEELCLIENT_API bool getMainPageOxygenLanceData(NavTreeIndex index, MainPageOxygenLanceData& out)
{
    return SteelClientData::getMainPageOxygenLanceData(index, out);
}

STEELCLIENT_API void setMainPageOxygenLanceField(NavTreeIndex index, const char* fieldName, double value)
{
    SteelClientData::setMainPageOxygenLanceField(index, fieldName, value);
}

STEELCLIENT_API void setMainPageChartData(NavTreeIndex index, const MainPageChartData& data)
{
    SteelClientData::setMainPageChartData(index, data);
}

STEELCLIENT_API bool getMainPageChartData(NavTreeIndex index, MainPageChartData& out)
{
    return SteelClientData::getMainPageChartData(index, out);
}

STEELCLIENT_API bool getMainPageChartTableData(NavTreeIndex index, MainPageChartTableData& out)
{
    return SteelClientData::getMainPageChartTableData(index, out);
}

STEELCLIENT_API void setMainPageChartTableData(NavTreeIndex index, const MainPageChartTableData& data)
{
    SteelClientData::setMainPageChartTableData(index, data);
}

STEELCLIENT_API void setMainPageChartTableItem(NavTreeIndex index, int row, int column, const char* value)
{
    SteelClientData::setMainPageChartTableItem(index, row, column, value);
}

STEELCLIENT_API void setMainPageOperStageData(NavTreeIndex index, const MainPageOperStageData& data)
{
    SteelClientData::setMainPageOperStageData(index, data);
}

STEELCLIENT_API bool getMainPageOperStageData(NavTreeIndex index, MainPageOperStageData& out)
{
    return SteelClientData::getMainPageOperStageData(index, out);
}

STEELCLIENT_API void setMainPageOperStageItem(NavTreeIndex index, int row, int column, const char* value)
{
    SteelClientData::setMainPageOperStageItem(index, row, column, value);
}

STEELCLIENT_API void setMainPageOperTotalData(NavTreeIndex index, const MainPageOperTotalData& data)
{
    SteelClientData::setMainPageOperTotalData(index, data);
}

STEELCLIENT_API bool getMainPageOperTotalData(NavTreeIndex index, MainPageOperTotalData& out)
{
    return SteelClientData::getMainPageOperTotalData(index, out);
}

STEELCLIENT_API void setMainPageOperTotalItem(NavTreeIndex index, int row, int column, const char* value)
{
    SteelClientData::setMainPageOperTotalItem(index, row, column, value);
}

STEELCLIENT_API void setMainPageProcessData(NavTreeIndex index, const MainPageProcessData& data)
{
    SteelClientData::setMainPageProcessData(index, data);
}

STEELCLIENT_API bool getMainPageProcessData(NavTreeIndex index, MainPageProcessData& out)
{
    return SteelClientData::getMainPageProcessData(index, out);
}

STEELCLIENT_API void setMainPageVideoData(NavTreeIndex index, const MainPageVideoData& data)
{
    SteelClientData::setMainPageVideoData(index, data);
}

STEELCLIENT_API bool getMainPageVideoData(NavTreeIndex index, MainPageVideoData& out)
{
    return SteelClientData::getMainPageVideoData(index, out);
}

STEELCLIENT_API SteelClientWindowHandle getMainPageVideoWindowHandle()
{
    MainWindow* mainWindow = g_mainWindow;
    if (!mainWindow) {
        qWarning() << "getMainPageVideoWindowHandle: main window not initialized";
        return 0;
    }

    if (QThread::currentThread() == mainWindow->thread()) {
        return fetchVideoWindowHandle();
    }

    SteelClientWindowHandle handle = 0;
    QMetaObject::invokeMethod(mainWindow, [&handle]() {
        handle = fetchVideoWindowHandle();
    }, Qt::BlockingQueuedConnection);

    return handle;
}

STEELCLIENT_API void setMainPageBlowingData(NavTreeIndex index, const MainPageBlowingData& data)
{
    SteelClientData::setMainPageBlowingData(index, data);
}

STEELCLIENT_API bool getMainPageBlowingData(NavTreeIndex index, MainPageBlowingData& out)
{
    return SteelClientData::getMainPageBlowingData(index, out);
}

STEELCLIENT_API void setMainPageBlowingField(NavTreeIndex index, const char* fieldName, const char* value)
{
    SteelClientData::setMainPageBlowingField(index, fieldName, value);
}

STEELCLIENT_API int unregisterCallback(int callbackId)
{
    if (APIDataManager::instance().unregisterCallback(callbackId)) {
        return 0;
    }
    qWarning() << "unregisterCallback failed for id" << callbackId;
    return -1;
}

STEELCLIENT_API int setVideoWidgetButtonDisplayMode(NavTreeIndex index, int mode)
{
    // 验证NavTreeIndex是否为有效的Main页面索引
    if (index != NavTreeIndex::Main_1 && index != NavTreeIndex::Main_2 &&
        index != NavTreeIndex::Main_3 && index != NavTreeIndex::Main_4 &&
        index != NavTreeIndex::Main_5 && index != NavTreeIndex::Main_6) {
        qWarning() << "setVideoWidgetButtonDisplayMode: invalid NavTreeIndex" << static_cast<int>(index);
        return -1;
    }

    // 验证模式值
    if (mode < 0 || mode > 2) {
        qWarning() << "setVideoWidgetButtonDisplayMode: invalid mode value" << mode;
        return -1;
    }

    // 存储按钮显示模式设置
    APIDataManager::instance().setVideoButtonDisplayMode(index, mode);

    // 如果当前显示的炉子是这个index，立即应用设置
    MainWindow* mainWindow = g_mainWindow;
    if (!mainWindow) {
        // UI未启动，只存储设置，稍后应用
        return 0;
    }

    MainPageWidget* mainPageWidget = mainWindow->getMainPageWidget();
    if (!mainPageWidget) {
        return 0;
    }

    MainOperationWidget* mainOperationWidget = mainPageWidget->getMainOperationWidget();
    if (!mainOperationWidget) {
        return 0;
    }

    // 如果当前显示的炉子是指定的index，立即应用设置
    NavTreeIndex currentIndex = mainOperationWidget->getCurrentNavIndex();
    if (currentIndex == index) {
        VideoWidget* videoWidget = mainOperationWidget->getVideoWidget();
        if (videoWidget) {
            // 转换为 VideoWidget::ButtonDisplayMode
            VideoWidget::ButtonDisplayMode displayMode;
            switch (mode) {
                case 0:
                    displayMode = VideoWidget::ShowBothButtons;
                    break;
                case 1:
                    displayMode = VideoWidget::ShowNormalButtonOnly;
                    break;
                case 2:
                    displayMode = VideoWidget::ShowAbnormalButtonOnly;
                    break;
                default:
                    displayMode = VideoWidget::ShowBothButtons;
                    break;
            }

            // 确保在主线程中执行
            if (QThread::currentThread() == mainWindow->thread()) {
                videoWidget->setButtonDisplayMode(displayMode);
            } else {
                QMetaObject::invokeMethod(mainWindow, [videoWidget, displayMode]() {
                    videoWidget->setButtonDisplayMode(displayMode);
                }, Qt::BlockingQueuedConnection);
            }
        }
    }

    return 0;
}

STEELCLIENT_API int setSmeltingConfigMoltenIronData(NavTreeIndex index, const ConfigWorkingConditionData::MoltenIronComposition& moltenIron)
{
    // 验证索引是否有效（应该是Config_1到Config_6）
    if (index < NavTreeIndex::Config_1 || index > NavTreeIndex::Config_6) {
        return -1;
    }
    
    // 获取当前的工况类数据
    ConfigWorkingConditionData data;
    if (!SteelClientData::getWorkingConditionData(index, data)) {
        // 如果数据不存在，创建一个新的默认数据
        data = ConfigWorkingConditionData();
    }
    
    // 更新铁水数据
    data.moltenIron = moltenIron;
    
    // 设置数据（这会触发回调）
    SteelClientData::setWorkingConditionData(index, data);
    
    // 更新UI（如果当前正在显示该配置）
    // 使用Qt的信号槽机制在线程安全的方式下更新UI
    if (g_mainWindow && QThread::currentThread() == QApplication::instance()->thread()) {
        // 在主线程中直接更新
        MainPageWidget* mainPageWidget = g_mainWindow->getMainPageWidget();
        if (mainPageWidget) {
            // 计算炉子索引（Config_1对应炉子0，Config_2对应炉子1，以此类推）
            int stoveIndex = (static_cast<int>(index) / 10) - 1;
            if (stoveIndex >= 0 && stoveIndex < 6) {
                // 获取SmeltingConfigWidget并更新数据
                SmeltingConfigWidget* smeltingConfigWidget = mainPageWidget->findChild<SmeltingConfigWidget*>();
                if (smeltingConfigWidget) {
                    smeltingConfigWidget->loadDataForStove(stoveIndex);
                }
            }
        }
    } else if (g_mainWindow) {
        // 在非主线程中，使用QMetaObject::invokeMethod异步更新
        QMetaObject::invokeMethod(QApplication::instance(), [index]() {
            if (g_mainWindow) {
                MainPageWidget* mainPageWidget = g_mainWindow->getMainPageWidget();
                if (mainPageWidget) {
                    int stoveIndex = (static_cast<int>(index) / 10) - 1;
                    if (stoveIndex >= 0 && stoveIndex < 6) {
                        SmeltingConfigWidget* smeltingConfigWidget = mainPageWidget->findChild<SmeltingConfigWidget*>();
                        if (smeltingConfigWidget) {
                            smeltingConfigWidget->loadDataForStove(stoveIndex);
                        }
                    }
                }
            }
        }, Qt::QueuedConnection);
    }
    
    return 0;
}

} // extern "C"
